/*
 * 文件简单通信协议：
 *  1）4 字节的文件名字节数（int）
 *  2）文件名（UTF-8 编码）
 *  3）8 字节的文件字节数（long）
 *  4）文件内容
 */

package addition.file;

import lombok.NonNull;

import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class FileServer {

    /**
     * 文件接收
     *
     * @param is InputStream
     * @throws IOException IOException
     */
    public static void receiveFile(@NonNull InputStream is) throws IOException {
        byte[] buffer = new byte[1024 * 4];

        // Wrap InputStream to DataInputStream
        DataInputStream dis = new DataInputStream(is);

        // Read filename
        int filenameLength = dis.readInt();  // filename length
        dis.readFully(buffer, 0, filenameLength);  // filename body
        String filename = new String(buffer, 0, filenameLength, StandardCharsets.UTF_8);  // covert to string

        // Read file body
        long fileLength = dis.readLong();  // file body length

        System.out.println("> FILENAME: " + filename);
        System.out.println("> FILE_LENGTH: " + fileLength);
        System.out.println("> FILENAME_LENGTH: " + filenameLength);

        try (FileOutputStream fos = new FileOutputStream(filename)) {
            while (fileLength > 0) {
                int readLength = dis.read(buffer);
                fos.write(buffer, 0, readLength);
                fileLength -= readLength;
            }
        }

        dis.close();
        System.out.println("> RECEIVE OK");
    }

    public static void main(String[] args) {
        try (ServerSocket server = new ServerSocket(8080)) {
            System.out.println("> SERVER STAT.");
            while (true) {
                Socket client = server.accept();

                // create new thread receive file
                new Thread(() -> {
                    try {
                        System.out.printf("> FROM [ %s ]%n", client.getRemoteSocketAddress());
                        receiveFile(client.getInputStream());
                        client.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
